<template>
  <!-- <a-modal
    :width="850"
    :visible="props.visible"
    @ok="handleOk"
    @cancel="handleCancel"
  > -->
  <!-- <template #title>  </template> -->
  <!-- 新增工作地址 -->
  <div style="width: 60%; margin: 0 auto">
    <a-form
      ref="formRef"
      :model="attendanceClockInAddress"
      autoLabelWidth
      label-align="right"
    >
      <!-- :rules="rules" -->
      <a-form-item
        field="organizationWorkPlaceId"
        label="工作地址"
        required
        show-colon
      >
        <a-select
          @change="(e)=> select(e as number)"
          v-model="attendanceClockInAddress.organizationWorkPlaceId"
          :field-names="{ value: 'id', label: 'name' }"
          :options="options.data"
          placeholder="请选择"
        >
        </a-select>
      </a-form-item>

      <a-form-item label="地址范围" required show-colon>
        <a-radio-group
          v-model="attendanceClockInAddress.scope"
          direction="horizontal"
        >
          <a-radio :value="1">圆形(半径范围)</a-radio>
          <a-radio :value="2">地理围栏</a-radio>
        </a-radio-group>
        <a-checkbox
          @change="(e)=>changeisAllowedInconsistency(e as boolean)"
          :model-value="isAllowedInconsistency"
        >
          手机定位于地点范围设定不一致，允许打卡
        </a-checkbox>
      </a-form-item>
      <a-form-item
        label="有效半径"
        required
        show-colon
        v-if="attendanceClockInAddress.scope === 1"
      >
        <a-input-number
          :model-value="attendanceClockInAddress.scopeInfo.circle.radius"
          @change="(e)=> isDistance(e as number)"
          :min="0"
          :style="{ width: '100px' }"
          allow-clear
          hide-button
        >
          <template #suffix> 米</template>
        </a-input-number>
      </a-form-item>
    </a-form>
    <template v-if="attendanceClockInAddress.scope === 2">
      <a-space
        style="
          display: flex;
          justify-content: space-between;
          margin-bottom: 10px;
        "
      >
        <div class="clockInType">
          <div :class="{ isClock: !clockInType }" @click="checkArea(false)">
            选择打卡区域
          </div>
          <div :class="{ isClock: clockInType }" @click="checkArea(true)">
            选择非打卡区域
          </div>
        </div>
        <a-space>
          <a-button type="primary" @click="addPolygon(2)">生成围栏</a-button>
          <a-button type="outline" @click="removeMarkers">重置</a-button>
        </a-space>
      </a-space>
      <a-space>
        <p>选择{{ !clockInType ? '' : '非' }}打卡区域 :</p>
        <a-button type="outline" @click="flag = true">开始选点</a-button>
        <a-button type="outline" @click="revoke">撤销</a-button>
        <a-button type="outline" @click="revoke">删除</a-button>
        <a-button type="outline" :disabled="clockInType" @click="addPolygon(1)"
          >生成多边形
        </a-button>
        <a-button type="primary" @click="removeMarkers">清空</a-button>
      </a-space>
    </template>
    <div id="maps"></div>
  </div>
  <!-- </a-modal> -->
</template>
<script setup lang="ts">
import * as Type from '../type';
import { cloneDeep } from 'lodash';
import {
  GetMapAddress,
  GetMapIpAddress
} from '@/apis/attendance/base-setting/index';
import { mapInit } from '@/utils/mapSdk';
import { GetWorkPlaceList } from '@/apis/management/organization/organizationManagement';
import { flattenArrayWithChildren } from '@/utils/utils';
import citiesJson from '@/assets/json/pc-code.json';
import { Message } from '@arco-design/web-vue';

const props = withDefaults(
  defineProps<{
    data: Type.TattendanceClockInAddress;
  }>(),
  {}
);

const attendanceClockInAddress = reactive<Type.TattendanceClockInAddress>({
  scope: 1,
  isAllowedInconsistency: 2,
  scopeInfo: {
    circle: { radius: 0, center: { longitude: 0, latitude: 0 } },
    polygon: {
      regularPolygon: [],
      fencePolygon: []
    }
  }
});
const pending: any = [];
watch(
  () => props.data,
  async (val) => {
    Object.assign(attendanceClockInAddress, val);
    if (mapApi.value) {
      if (val.organizationWorkPlaceId)
        await changePendingData(1, val.organizationWorkPlaceId);
      if (val.scopeInfo.circle.radius) {
        location.value = [];
        location.value[0] = val.scopeInfo.circle.center.longitude;
        location.value[1] = val.scopeInfo.circle.center.latitude;
        changePendingData(4, val.scopeInfo.circle.radius);
      }
      if (val?.scopeInfo?.polygon?.fencePolygon.length !== 0) {
        val.scopeInfo.polygon.fencePolygon.forEach((ele, index) => {
          const newData = cloneDeep(ele);
          newData.index = index;
          pending.push({
            data: cloneDeep(ele),
            type: 3
          });
        });
      }
      if (val?.scopeInfo?.polygon?.regularPolygon.length !== 0) {
        val.scopeInfo.polygon.regularPolygon.forEach((ele, index) => {
          changePendingData(2, ele);
        });
      }
    } else {
      if (val.organizationWorkPlaceId)
        pending.push({ type: 1, data: val.organizationWorkPlaceId });
      if (val.scopeInfo.circle.radius) {
        location.value = [];
        location.value[0] = val.scopeInfo.circle.center.longitude;
        location.value[1] = val.scopeInfo.circle.center.latitude;
        pending.push({ type: 4, data: val.scopeInfo.circle.radius });
      }
      if (val?.scopeInfo?.polygon?.regularPolygon.length !== 0) {
        val.scopeInfo.polygon.regularPolygon.forEach((ele) => {
          pending.push({
            data: cloneDeep(ele),
            type: 2
          });
        });
      }
      if (val?.scopeInfo?.polygon?.fencePolygon.length !== 0) {
        val.scopeInfo.polygon.fencePolygon.forEach((ele, index) => {
          const newData = cloneDeep(ele);
          newData.index = index;
          pending.push({
            data: cloneDeep(ele),
            type: 3
          });
        });
      }
    }
  }
);

const isAllowedInconsistency = computed(() => {
  if (attendanceClockInAddress.isAllowedInconsistency === 1) {
    return true;
  } else {
    return false;
  }
});

const flag = ref(false);
const markerArr = reactive<number[][]>([]); // 存储点的经纬度
const markersData = reactive<any>([]); // 存储点的数据
const polygon = reactive<any>([]); // 存储多边形的数据
const polygonArr = reactive<any>({}); // 存储多边形的经纬度
const polygonId = ref(0); // 要生成围栏选中的多边形
const polygons = reactive<any>([]); // 存储多边形围栏的数据
const pointers = reactive<
  {
    outer: number[][];
    inner: number[][];
  }[]
>([]); // 存储多边形的经纬度

let cityData = flattenArrayWithChildren(citiesJson); // 储存扁平化后的数据
const location = ref<number[]>([]);
let circle = ref();
const marker = ref();
const clockInType = ref(false); // 区分打卡区域与非打卡区域
const options: any = reactive({ data: [] });
const emit = defineEmits(['update']);
const init = async () => {
  const res = await GetWorkPlaceList({ pageNumber: 0, pageSize: -1 });
  options.data = res.content;
  options.data.forEach((ele: any) => {
    ele.cityCode =
      cityData.find((item) => item.code === ele.cityCode.slice(0, 2))?.name +
      cityData.find((item) => item.code === ele.cityCode)?.name;
  });
};
const map = ref<any>(null);
const mapApi = ref<any>(null);

init();

watch(
  () => flag.value,
  (val) => {
    if (!location.value) {
      return Message.error('请选择地点');
    }
    if (val) {
      map.value.on('click', showInfoClick);
    } else {
      map.value.off('click', showInfoClick);
    }
  }
);
const changePendingData = async (type: 1 | 2 | 3 | 4, data: any) => {
  if (type === 1) {
    await select(data);
  } else if (type === 2) {
    polygon.push(
      new mapApi.value.Polygon({
        path: data,
        strokeColor: '#2a7b38',
        strokeWeight: 3,
        strokeOpacity: 0.7,
        fillOpacity: 0.4,
        fillColor: '#abfcba',
        zIndex: 50
      })
    );
    polygonArr[polygon[polygon.length - 1]['_amap_id']] = cloneDeep(data);
    map.value.add(polygon[polygon.length - 1]);
  } else if (type === 3) {
    polygons.push(
      new mapApi.value.Polygon({
        map: map.value,
        strokeColor: '#2a7b38',
        strokeWeight: 3,
        fillColor: '#abfcba',
        fillOpacity: 0.7
      })
    );
    pointers[data.index] = { outer: [], inner: [] };
    polygons[polygons.length - 1].setPath([data.outer, data.inner]);
    pointers[data.index].outer = data.outer;
    pointers[data.index].inner = data.inner;
  } else if (type === 4) {
    //
    isDistance(data);
  }
};
// 重置数据
const removeMarkers = () => {
  map.value.remove(markersData);
  markersData.length = 0;
  markerArr.length = 0;
  revokePolygon();
  map.value.remove(polygons);
};
// 删除点的数据
const revoke = () => {
  if (markersData.length === 0) return;
  markersData[markersData.length - 1].setMap(null);
  markersData.splice(markersData.length - 1, 1);
  markerArr.splice(markersData.length - 1, 1);
};

const revokePolygon = () => {
  for (let key in polygonArr) {
    delete polygonArr[key];
  }
  pointers.length = 0;
  addRegularPolygon();
  map.value.remove(polygon);
};
watch(polygonArr, (val) => {
  attendanceClockInAddress.scopeInfo.polygon.regularPolygon.length = 0;
  if (Object.keys(val).length === 0) return;
  for (let key in val) {
    attendanceClockInAddress.scopeInfo.polygon.regularPolygon.push(val[key]);
  }
});

const addRegularPolygon = () => {
  attendanceClockInAddress.scopeInfo.polygon.fencePolygon.length = 0;
  if (pointers.length === 0) return;
  pointers.forEach((ele) => {
    attendanceClockInAddress.scopeInfo.polygon.fencePolygon.push(ele);
  });
};
watch(
  () => attendanceClockInAddress.scope,
  (val) => {
    if (val === 1) {
      removeMarkers();
    } else {
      attendanceClockInAddress.scopeInfo.circle.center.longitude = 0;
      attendanceClockInAddress.scopeInfo.circle.center.latitude = 0;
      attendanceClockInAddress.scopeInfo.circle.radius = 0;
      if (circle.value) {
        map.value.remove(circle.value);
      }
    }
  }
);
// 新增多边形与地理围栏
const addPolygon = (type: 1 | 2) => {
  if (markerArr.length === 0) return Message.error('操作失误');
  if (type === 1) {
    polygon.push(
      new mapApi.value.Polygon({
        path: markerArr,
        strokeColor: '#2a7b38',
        strokeWeight: 3,
        strokeOpacity: 0.7,
        fillOpacity: 0.4,
        fillColor: '#abfcba',
        zIndex: 50
      })
    );
    polygonArr[polygon[polygon.length - 1]['_amap_id']] = cloneDeep(markerArr);
    map.value.add(polygon[polygon.length - 1]);
  } else {
    if (!clockInType.value)
      return Message.error('未选择未打卡区域无法生成围栏');
    polygons.push(
      new mapApi.value.Polygon({
        map: map.value,
        strokeColor: '#2a7b38',
        strokeWeight: 3,
        fillColor: '#abfcba',
        fillOpacity: 0.7
      })
    );
    map.value.remove(
      polygon.filter((ele: any) => ele._amap_id === polygonId.value)
    );
    polygons[polygons.length - 1].setPath([
      pointers[pointers.length - 1].outer,
      pointers[pointers.length - 1].inner
    ]);
    delete polygonArr[polygonId.value];
    addRegularPolygon();
    polygonId.value = 0;
  }
  markersData.forEach((ele: any) => ele.setMap(null));
  markersData.length = 0;
  markerArr.length = 0;
};

// 鼠标点击事件
const showInfoClick = (e: any) => {
  markerArr.push([e.lnglat.getLng(), e.lnglat.getLat()]);
  markersData.push(
    new mapApi.value.Marker({
      map: map.value,
      icon: `https://webapi.amap.com/theme/v1.3/markers/n/mark_b.png`,
      position: [e.lnglat.getLng(), e.lnglat.getLat()],
      offset: new mapApi.value.Pixel(-13, -30)
    })
  );
  // 围栏操作
  if (clockInType.value) {
    if (polygonId.value) {
      if (e.target._amap_id !== polygonId.value) {
        markersData[markersData.length - 1].setMap(null);
        markersData.splice(markersData.length - 1, 1);
        markerArr.splice(markersData.length - 1, 1);
        return Message.error('所选多边形不一致');
      }
      pointers[pointers.length - 1].inner.push([
        e.lnglat.getLng(),
        e.lnglat.getLat()
      ]);
    } else {
      polygonId.value = e.target._amap_id;
      pointers[pointers.length] = { outer: [], inner: [] };
      pointers[pointers.length - 1].outer = polygonArr[e.target._amap_id];
      pointers[pointers.length - 1].inner.push([
        e.lnglat.getLng(),
        e.lnglat.getLat()
      ]);
    }
  }
};

const initMap = async () => {
  try {
    const res = await GetMapIpAddress();
    const mapData = await mapInit();
    mapApi.value = mapData;
    map.value = new mapData.Map('maps', {
      resizeEnable: true,
      zoom: 18,
      center: res.rectangle
        .split(';')[0]
        .split(',')
        .map((ele: string) => Number(ele))
    });
    if (pending.length !== 0) {
      for (const iterator of pending) {
        await changePendingData(iterator.type, iterator.data);
      }
      // pending.forEach(({ data, type }: any) => {});
    }
  } catch (error) {
    console.log(error);
    Message.error('地图加载失败');
  }
};

const isMarker = (position: number[]) => {
  marker.value = new mapApi.value.Marker({
    icon: 'https://webapi.amap.com/theme/v1.3/markers/n/mark_b.png',
    position: position
  });
  map.value.setCenter(position);
  map.value.add(marker.value);
};

const isCircle = (distance: number) => {
  circle.value = new mapApi.value.Circle({
    center: new mapApi.value.LngLat(...location.value),
    radius: distance,
    strokeColor: '#81bff2',
    strokeOpacity: 1,
    strokeWeight: 3,
    fillColor: '#d4e9fb',
    fillOpacity: 0.35
  });
  map.value.add(circle.value);
};

const isDistance = (e: number) => {
  if (!location.value) {
    return Message.error('请选择地点');
  }
  if (circle.value) {
    map.value.remove(circle.value);
  }
  if (e) {
    isCircle(e);
  } else {
    map.value.remove(circle);
  }
  attendanceClockInAddress.scopeInfo.circle.radius = e;
  attendanceClockInAddress.scopeInfo.circle.center.longitude =
    location.value[0];
  attendanceClockInAddress.scopeInfo.circle.center.latitude = location.value[1];
};
/**
 * 更新数据
 */
const upData = () => {
  emit('update', attendanceClockInAddress);
};

const select = async (id: number) => {
  const { address, cityCode, name } = options.data.filter(
    (ele: any) => ele.id === id
  )[0];
  attendanceClockInAddress.organizationWorkPlaceId = id;
  if ((!!address || !!name) && !!cityCode) {
    const res = await GetMapAddress({
      address: cityCode + (address ? address : name)
    });
    if (marker.value) map.value.remove(marker.value);
    if (circle.value) map.value.remove(circle.value);
    location.value = res.geocodes[0].location
      .split(',')
      .map((ele: string) => Number(ele));
    isMarker(location.value);
  }
};

// 打卡区域数据
const checkArea = (check: boolean) => {
  if (check) {
    if (polygon.length === 0) {
      return Message.error('没有可以生成围栏的多边形');
    }
    clockInType.value = check;
    flag.value = !check;
    polygon.forEach((ele: any) => {
      ele.on('click', showInfoClick);
    });
  } else {
    clockInType.value = check;
    flag.value = !check;
    polygon.forEach((ele: any) => {
      ele.off('click', showInfoClick);
    });
  }
};

const changeisAllowedInconsistency = (e: boolean) => {
  if (e) attendanceClockInAddress.isAllowedInconsistency = 1;
  else attendanceClockInAddress.isAllowedInconsistency = 2;
};

onMounted(() => {
  try {
    initMap(); // 初始化地图
  } catch (error) {
    console.log(error);
    Message.error('地图加载失败请稍后重试');
  }
});
defineExpose({ upData });
</script>
<style lang="less" scoped>
#maps {
  height: 400px;
}
.clockInType {
  display: flex;
  div {
    margin: 0;
    padding: 5px;
    border: 1px solid #e4e4e4;
    cursor: pointer;
  }
  div:nth-child(1) {
    border-right: none;
    border-bottom-left-radius: 5px;
    border-top-left-radius: 5px;
  }
  div:nth-child(2) {
    border-bottom-right-radius: 5px;
    border-top-right-radius: 5px;
  }
  .isClock {
    background-color: #e4e4e4;
  }
}
</style>
